﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BitPortal.Models;
using System.Linq.Expressions;
using Ext.Net;
using System.Collections.ObjectModel;
using System.Collections;
using BitPortal.Business;

namespace BitPortal.ExtNet
{
    public static class GirdData
    {
        /// <summary>
        /// Tim kiem , sap xep, phan trang tren girdpanel
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="fc"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        public static List<T> Filter<T>(this List<T> data, Ext.Net.FilterConditions fc, StoreRefreshDataEventArgs e = null)
        {
            if (fc != null)
            {
                foreach (FilterCondition condition in fc.Conditions)
                {
                    Comparison comparison = condition.Comparison;
                    string field = condition.Name;
                    FilterType type = condition.FilterType;

                    object value;
                    switch (condition.FilterType)
                    {
                        case FilterType.Boolean:
                            value = condition.ValueAsBoolean;
                            break;
                        case FilterType.Date:
                            value = condition.ValueAsDate;
                            break;
                        case FilterType.List:
                            value = condition.ValuesList;
                            break;
                        case FilterType.Numeric:
                            if (data.Count() > 0 && data.First().GetPropertyValue(field).GetType() == typeof(int))
                            {
                                value = condition.ValueAsInt;
                            }
                            else if (data.Count() > 0 && data.First().GetPropertyValue(field).GetType() == typeof(Int64))
                            {
                                value = Convert.ToInt64(condition.Value);
                            }
                            else if (data.Count() > 0 && data.First().GetPropertyValue(field).GetType() == typeof(Double))
                            {
                                value = Convert.ToDouble(condition.Value);
                            }
                            else value = Convert.ToDecimal(condition.Value);
                            break;
                        case FilterType.String:
                            value = condition.Value;
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                    data.RemoveAll(
                        item =>
                        {
                            object oValue = item.GetPropertyValue(condition.Name);
                            IComparable cItem = oValue as IComparable;

                            switch (comparison)
                            {
                                case Comparison.Eq:

                                    switch (type)
                                    {
                                        case FilterType.List:
                                            return !(value as ReadOnlyCollection<string>).Contains(oValue.ToString());
                                        case FilterType.String:
                                            return !oValue.ToString().StartsWith(value.ToString());
                                        default:
                                            return !cItem.Equals(value);
                                    }

                                case Comparison.Gt:
                                    return cItem.CompareTo(value) < 1;
                                case Comparison.Lt:
                                    return cItem.CompareTo(value) > -1;
                                default:
                                    throw new ArgumentOutOfRangeException();
                            }
                        }
                    );
                }
            }
            //-- end filtering ------------------------------------------------------------
            List<T> rangeData = data;
            if (e != null)
            {
                //-- start sorting ------------------------------------------------------------
                if (!string.IsNullOrEmpty(e.Sort))
                {
                    data.Sort(delegate(T x, T y)
                    {
                        object a;
                        object b;

                        int direction = e.Dir == Ext.Net.SortDirection.DESC ? -1 : 1;
                        a = x.GetPropertyValue(e.Sort);
                        b = y.GetPropertyValue(e.Sort);
                        return CaseInsensitiveComparer.Default.Compare(a, b) * direction;
                    });
                }
                //-- end sorting -------------------------------------------------------------
                //-- start paging ------------------------------------------------------------
                var limit = e.Limit;

                if ((e.Start + e.Limit) > data.Count)
                {
                    limit = data.Count - e.Start;
                }

                rangeData = (e.Start < 0 || limit < 0) ? data : data.GetRange(e.Start, limit);
                //-- end paging ------------------------------------------------------------
                e.Total = data.Count;
            }
            return rangeData;
        }
    }
}